package com.oss.service.system;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.oss.common.BaseResponse;
import com.oss.dto.rights.RightsAddDto;
import com.oss.dto.rights.RightsDeleteDto;
import com.oss.dto.rights.RightsListDto;
import com.oss.dto.rights.RightsUpdateDto;
import com.oss.entity.system.Rights;
import com.oss.entity.system.RoleRights;
import com.oss.entity.system.UserRole;
import com.oss.enums.IsDeletedEnum;
import com.oss.enums.RightsTypeEnum;
import com.oss.enums.UserStatusEnum;
import com.oss.mapper.system.RightsMapper;
import com.oss.mapper.system.RoleMapper;
import com.oss.mapper.system.RoleRightsMapper;
import com.oss.mapper.system.UserRoleMapper;
import com.oss.util.SnowFlakeUtil;
import com.oss.vo.rights.RightsVO;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author chengqiang
 */
@Service
public class RightsService extends ServiceImpl<RightsMapper, Rights> {
    @Autowired
    RightsMapper rightsMapper;
    @Autowired
    UserRoleMapper userRoleMapper;
    @Autowired
    RoleRightsMapper roleRightsMapper;
    @Autowired
    RoleMapper roleMapper;

    /**
     * 新增权限
     * 权限代码和名称都不能重复
     * @param dto 入参
     * @return 返回值
     */
    public BaseResponse addRights(RightsAddDto dto) {
        LambdaQueryWrapper<Rights> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(Rights::getIsDeleted, IsDeletedEnum.NO.getFlag());
        lambdaQueryWrapper.and(wrapper->
                wrapper.eq(Rights::getRightsCode,dto.getRightsCode())
                        .or()
                        .eq(Rights::getRightsName,dto.getRightsName())
        );
        long count = rightsMapper.selectCount(lambdaQueryWrapper);
        if (count > 0){
            return BaseResponse.error("权限代码或名称已存在");
        }
        Rights entity = new Rights();
        BeanUtils.copyProperties(dto,entity);
        entity.setRightsId(SnowFlakeUtil.getID());
        entity.setRightsStatus(UserStatusEnum.enable.getKey());
        if (StringUtils.isBlank(dto.getParentRightsId())){
            entity.setParentRightsId("0");
        }
        rightsMapper.insert(entity);
        return BaseResponse.success("操作成功");
    }

    /**
     * 删除权限, 同时删除子权限
     * @param dto 入参
     * @return 返回值
     */
    public String deleteRights(RightsDeleteDto dto) {
        Set<String> ids = new HashSet<>();
        LambdaQueryWrapper<Rights> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(Rights::getParentRightsId,dto.getRightsId());
        // 当前菜单的子菜单(可以视为二级菜单)
        Set<String> childrenIds2 = rightsMapper.selectList(lambdaQueryWrapper).stream().map(Rights::getRightsId).collect(Collectors.toSet());
        ids.add(dto.getRightsId());
        if (CollectionUtils.isNotEmpty(childrenIds2)) {
            ids.addAll(childrenIds2);
            //当前菜单的孙子菜单(可以视为三级菜单)
            Set<String> childrenIds3 = rightsMapper.selectBatchIds(childrenIds2).stream().map(Rights::getRightsId).collect(Collectors.toSet());
            if (CollectionUtils.isNotEmpty(childrenIds3)) {
                ids.addAll(childrenIds3);
            }
        }
        LambdaUpdateWrapper<Rights> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        lambdaUpdateWrapper.set(Rights::getIsDeleted, IsDeletedEnum.YES.getFlag());
        lambdaUpdateWrapper.in(Rights::getRightsId,ids);
        rightsMapper.update(null,lambdaUpdateWrapper);
        return "操作成功";
    }

    public BaseResponse<String> updateRights(RightsUpdateDto dto) {
        // 校验当前修改的权限, 是否存在形同的code和名称
        LambdaQueryWrapper<Rights> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(Rights::getIsDeleted,IsDeletedEnum.NO.getFlag());
        lambdaQueryWrapper.ne(Rights::getRightsId,dto.getRightsId());
        lambdaQueryWrapper.and(wrapper->
                wrapper.eq(Rights::getRightsCode,dto.getRightsCode())
                        .or()
                        .eq(Rights::getRightsName,dto.getRightsName())
        );
        long count = rightsMapper.selectCount(lambdaQueryWrapper);
        if (count > 0){
            return BaseResponse.error("权限代码或名称已存在");
        }
        LambdaUpdateWrapper<Rights> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        lambdaUpdateWrapper.eq(Rights::getRightsId,dto.getRightsId());
        Rights entity = new Rights();
        BeanUtils.copyProperties(dto,entity);
        rightsMapper.update(entity,lambdaUpdateWrapper);
        return BaseResponse.success("操作成功");
    }
    public BaseResponse listAll(RightsListDto dto) {
        // 返回值
        BaseResponse baseResponse = new BaseResponse<>();
        baseResponse.setCode(1);
        LambdaQueryWrapper<Rights> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(Rights::getIsDeleted,IsDeletedEnum.NO.getFlag());
        lambdaQueryWrapper.eq(StringUtils.isNotBlank(dto.getParentRightsId()), Rights::getParentRightsId,dto.getParentRightsId());
        lambdaQueryWrapper.eq(StringUtils.isNotBlank(dto.getRightsCode()), Rights::getRightsCode,dto.getRightsCode());
        lambdaQueryWrapper.like(StringUtils.isNotBlank(dto.getRightsName()), Rights::getRightsName,dto.getRightsName());
        lambdaQueryWrapper.in(CollectionUtils.isNotEmpty(dto.getRightsTypeList()), Rights::getRightsType,dto.getRightsTypeList());
        lambdaQueryWrapper.in(CollectionUtils.isNotEmpty(dto.getIsHiddenList()), Rights::getIsHidden,dto.getIsHiddenList());
        lambdaQueryWrapper.in(CollectionUtils.isNotEmpty(dto.getRightsStatusList()), Rights::getRightsStatus,dto.getRightsStatusList());
        lambdaQueryWrapper.orderByAsc(Rights::getSort);
        List<Rights> listAll = rightsMapper.selectList(lambdaQueryWrapper);
        List<RightsVO> listVO = listAll.stream().map(entity->{
            RightsVO vo = new RightsVO();
            BeanUtils.copyProperties(entity,vo);
            vo.setRightsTypeName(RightsTypeEnum.getEnumDescByKey(entity.getRightsType()));
            vo.setRightsStatusName(UserStatusEnum.getStatusEnumsDescByKey(entity.getRightsStatus()));
            return vo;
        }).collect(Collectors.toList());
        if (dto.getMenuSelect() == 0) {
            // 按钮权限
            List<RightsVO> btnList = listVO.stream().filter(item->item.getRightsType() == 2).collect(Collectors.toList());
            // 菜单权限
            listVO = listVO.stream().filter(item->item.getRightsType() != 2).collect(Collectors.toList());
            baseResponse.setExtraData(btnList);
        }
        // 返回值
        List<RightsVO> returnList = new ArrayList<>();
        // 所有菜单的ID
        List<String> ids = listVO.stream().map(RightsVO::getRightsId).collect(Collectors.toList());
        // 获取父菜单不在列表中的 , 视为本次搜索的顶级菜单
        List<RightsVO> list1 = listVO.stream().filter(item-> !ids.contains(item.getParentRightsId())).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(list1)) {
            return BaseResponse.success(new ArrayList<RightsVO>());
        }
        // 一级菜单ID
        Set<String> rightsIds1 = list1.stream().map(RightsVO::getRightsId).collect(Collectors.toSet());
        // 二级菜单
        List<RightsVO> list2 = listVO.stream().filter(item->rightsIds1.contains(item.getParentRightsId())).collect(Collectors.toList());
        // 把二级菜单添加到对应的一级菜单中去
        list1.forEach(item->{
            List<RightsVO> children;
            if (CollectionUtils.isEmpty(item.getChildren())) {
                children = new ArrayList<>();
            } else {
                children = item.getChildren();
            }
            List<RightsVO> tempChildren = list2.stream().filter(item2->item2.getParentRightsId().equals(item.getRightsId())).collect(Collectors.toList());
            children.addAll(tempChildren);
            item.setChildren(children);
        });
        // 二级菜单ID
        Set<String> rightsIds2 = list2.stream().map(RightsVO::getRightsId).collect(Collectors.toSet());
        // 三级菜单
        List<RightsVO> list3 = listVO.stream().filter(item->rightsIds2.contains(item.getParentRightsId())).collect(Collectors.toList());
        // 把三级菜单添加到对应的二级菜单中去
        list2.forEach(item->{
            List<RightsVO> children;
            if (CollectionUtils.isEmpty(item.getChildren())) {
                children = new ArrayList<>();
            } else {
                children = item.getChildren();
            }
            List<RightsVO> tempChildren = list3.stream().filter(item2->item2.getParentRightsId().equals(item.getRightsId())).collect(Collectors.toList());
            children.addAll(tempChildren);
            item.setChildren(children);
        });
        returnList.addAll(list1);
        baseResponse.setData(returnList);
        return baseResponse;
    }

    public List<Rights> getRightsByUserId(String userId) {
        // 获取用户角色关联表
        LambdaQueryWrapper<UserRole> userRoleLambdaQueryWrapper = new LambdaQueryWrapper<>();
        userRoleLambdaQueryWrapper.eq(UserRole::getUserId,userId);
        userRoleLambdaQueryWrapper.eq(UserRole::getIsDeleted,IsDeletedEnum.NO.getFlag());
        List<UserRole> userRoleList = userRoleMapper.selectList(userRoleLambdaQueryWrapper);
        Set<String> roleIdSet = userRoleList.stream().map(UserRole::getRoleId).collect(Collectors.toSet());
        if (roleIdSet.isEmpty()) {
            return null;
        }
        // 获取角色和权限的关联表信息
        LambdaQueryWrapper<RoleRights> roleRightsLambdaQueryWrapper = new LambdaQueryWrapper<>();
        roleRightsLambdaQueryWrapper.eq(RoleRights::getIsDeleted,IsDeletedEnum.NO.getFlag());
        roleRightsLambdaQueryWrapper.in(RoleRights::getRoleId,roleIdSet);
        List<RoleRights> roleRightsList = roleRightsMapper.selectList(roleRightsLambdaQueryWrapper);
        Set<String> rightsIdSet = roleRightsList.stream().map(RoleRights::getRightsId).collect(Collectors.toSet());
        if (rightsIdSet.isEmpty()) {
            return null;
        }
        // 获取所有权限
        return rightsMapper.selectBatchIds(rightsIdSet);
    }

    public List<RightsVO> getParentRightsList() {
        LambdaQueryWrapper<Rights> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(Rights::getIsDeleted,IsDeletedEnum.NO.getFlag());
        lambdaQueryWrapper.orderByAsc(Rights::getSort);
        List<Rights> listAll = rightsMapper.selectList(lambdaQueryWrapper);
        List<RightsVO> listVO = listAll.stream().map(entity->{
            RightsVO vo = new RightsVO();
            BeanUtils.copyProperties(entity,vo);
            return vo;
        }).collect(Collectors.toList());
        // 返回值
        List<RightsVO> returnList = new ArrayList<>();
        // 获取一级菜单
        List<RightsVO> list1 = listVO.stream().filter(item->"0".equals(item.getParentRightsId())).collect(Collectors.toList());
        // 一级菜单ID
        Set<String> rightsIds1 = list1.stream().map(RightsVO::getRightsId).collect(Collectors.toSet());
        // 二级菜单
        List<RightsVO> list2 = listVO.stream().filter(item->rightsIds1.contains(item.getParentRightsId())).collect(Collectors.toList());
        // 把二级菜单添加到对应的一级菜单中去
        list1.forEach(item->{
            List<RightsVO> children;
            if (CollectionUtils.isEmpty(item.getChildren())) {
                children = new ArrayList<>();
            } else {
                children = item.getChildren();
            }
            List<RightsVO> tempChildren = list2.stream().filter(item2->item2.getParentRightsId().equals(item.getRightsId())).collect(Collectors.toList());
            children.addAll(tempChildren);
            item.setChildren(children);
        });
        returnList.addAll(list1);
        return returnList;
    }

    public RightsVO getRightsById(String rightsId) {
        RightsVO vo = new RightsVO();
        Rights entity = rightsMapper.selectById(rightsId);
        BeanUtils.copyProperties(entity,vo);
        if (StringUtils.isNotBlank(vo.getParentRightsId())) {
            Rights parentEntity = rightsMapper.selectById(vo.getParentRightsId());
            if (parentEntity != null){
                vo.setParentRightsName(parentEntity.getRightsName());
            }
        }
        return vo;
    }

    /**
     * 根据权限ID获取他的所有父节点
     * @param rightsIdList
     * @return
     */
    public Set<String> getRightsList(Set<String> rightsIdList) {
        if(CollectionUtils.isNotEmpty(rightsIdList)){
            List<Rights> list = rightsMapper.selectBatchIds(rightsIdList);
            Set<String> set = new HashSet<>();
            set.addAll(rightsIdList);
            LambdaQueryWrapper<Rights> lambdaQueryWrapper = new LambdaQueryWrapper<>();
            lambdaQueryWrapper.eq(Rights::getIsDeleted,IsDeletedEnum.NO.getFlag());
            // 所有权限
            List<Rights> listAll = rightsMapper.selectList(lambdaQueryWrapper);
            for (Rights entity : list){
                // 父节点
                List<Rights>  parentList = listAll.stream().filter(item->item.getRightsId().equals(entity.getParentRightsId())).collect(Collectors.toList());
                if (CollectionUtils.isNotEmpty(parentList)) {
                    set.addAll(parentList.stream().map(Rights::getRightsId).collect(Collectors.toSet()));
                    for (Rights tr : parentList) {
                        // 父节点的父节点
                        List<Rights>  parentList2 = listAll.stream().filter(item->item.getRightsId().equals(tr.getParentRightsId())).collect(Collectors.toList());
                        if (CollectionUtils.isNotEmpty(parentList2)) {
                            set.addAll(parentList2.stream().map(Rights::getRightsId).collect(Collectors.toSet()));
                        }
                    }
                }
            }
            return set;
        } else {
            return new HashSet<>();
        }
    }
}
